package com.cn.JUC.utils.case2;

import com.sun.deploy.nativesandbox.comm.Response;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @Title Double同步转异步
 * @Description 在 TCP 协议层面，发送完 RPC 请求后，线程是不会等待 RPC 的响应结果的。
 * 但是知名的 RPC 框架 Dubbo 确实同步的，它是如何做了异步转同步的事情？看下面代码实现
 * @Author CAI ZHAI
 * @Date 2021/9/1 21:59
 **/
public class DoubleImpl{
    Response response;
    
    // 创建锁与条件变量
    private final Lock lock = new ReentrantLock();
    private final Condition done = lock.newCondition();
    
    // 调用方通过该方法等待结果
    Object get(int timeout) throws Exception{
        long start = System.nanoTime();
        lock.lock();
        try {
            while (!isDone()) {
                done.await(timeout, TimeUnit.SECONDS);      //关键在于这一步：不阻塞了，要么是超时，要么是被唤醒
                long cur=System.nanoTime();
                if (isDone() || cur-start > timeout){
                    break;
                }
            }
        } finally {
            lock.unlock();
        }
        if (!isDone()) {
            throw new TimeoutException();
        }
        //return returnFromResponse();
        return new Object();
    }
    // RPC结果是否已经返回
    private boolean isDone() {
        return response != null;
    }
    // RPC结果返回时调用该方法
    private void doReceived(Response res) {
        lock.lock();
        try {
            response = res;
            if (done != null) {
                done.signal();
            }
        } finally {
            lock.unlock();
        }
    }
}

//疑问1：while (!isDone()) 这里while的作用是？
